#include "commandfactory.h"

#include <iostream>
using std::endl;
using std::cout;
using std::string;

#include <exception>
using std::exception;

#include "command/unknowncommand.h"
using Commands::UnknownCommand;
#include <sstream>
using std::ostringstream;

#include <Poco/StringTokenizer.h>
using Poco::StringTokenizer;

#include <Poco/DOM/AutoPtr.h>
using Poco::AutoPtr;
#include <Poco/DOM/DOMParser.h>
using Poco::XML::DOMParser;
#include <Poco/DOM/Document.h>
using Poco::XML::Document;
#include <Poco/DOM/NodeIterator.h>
#include <Poco/DOM/NodeFilter.h>
using Poco::XML::NodeIterator;
#include <Poco/DOM/Node.h>
using Poco::XML::Node;
#include <Poco/DOM/NamedNodeMap.h>
using Poco::XML::NamedNodeMap;

namespace Commands
{
	/**
	 * Used to create commands. The Factory design pattern is used here. We might want to implement new commands later.
	 */
	CommandFactory::CommandFactory() :
		_register()
	{}

	CommandFactory::CommandFactory(const vector<Command*>& commands) :
		_register()
	{
		for (vector<Command*>::const_iterator it = commands.begin(); it != commands.end(); ++it)
		{
			_register[(*it)->name()] = (*it)->creator();
		}
	}

	CommandFactory::CommandFactory(const CommandFactory& factory) :
		_register(factory._register)
	{}

	Command* CommandFactory::makeCommand(const string& repr, void* userdata)
	{
		cout << "CommandFactory :: Going to create a command." << endl;
		cout << "CommandFactory :: Representational string :: " << repr << endl;
		DOMParser parser;
		cout << "CommandFactory :: Created a parser" << endl;
		AutoPtr<Document> pDoc = parser.parseString(repr);
		cout << "CommandFactory :: Parsed the xml" << endl;
		NodeIterator it(pDoc, Poco::XML::NodeFilter::SHOW_ELEMENT);
		Node* node = it.nextNode();
	//	cout << "CommandFactory :: Printing the found Node :: " << node->attributes() << endl;
		//TODO something that extracts the methodname from the XML format and looks it up in the register
		NamedNodeMap* attrs = node->attributes();
		Node* attr = attrs->getNamedItem(Poco::XML::toXMLString("name"));
		cout << "CommandFactory :: Command Name :: " << attr->getNodeValue() << endl;
		string cmdName = Poco::XML::fromXMLString(attr->getNodeValue());
		CommandCreator cc = _register[cmdName];
		cout << "CommandFactory :: Looked up the command" << endl;
		if (cc == 0)
		{
			cout << "CommandFactory :: It seems this command is not implemented" << endl;
			throw NotImplemented();
			//return new UnknownCommand(repr);
		}
		cout << "CommandFactory :: Going to create command '" << cmdName << "'" << endl;
		Command* cmd = cc(repr, userdata);

		cout << "CommandFactory :: Job's Done" << endl;
		return cmd;
	}

	void CommandFactory::registerCommand(Command* cmd)
	{
		CommandCreator cc = cmd->creator();
		_register[cmd->name()] = cc;
	}

	void CommandFactory::unregisterCommand(Command* cmd)
	{
		_register.erase(_register.find(cmd->name()));
	}

	bool CommandFactory::isCommand(const string& string)
	{
		DOMParser parser;
		AutoPtr<Document> pDoc = parser.parseString(string);
		NodeIterator it(pDoc, Poco::XML::NodeFilter::SHOW_ELEMENT);
		Node* node = it.nextNode();
		if(node->localName() == "command"){
			cout << "CommandFactory :: isCommand :: We have a command" << endl;
			return true;
		}else{
			return false;
		}
	}

}
